OpenGL in C++

July 2003

Frequently a game or demo will use a wide field of view for a scene, and it looks pretty good until the camera starts to rotate- there's a bizarre warping (or lack of warping) at the edges of the screen that probably doesn't help the motion sick types at all. This is due to the way scenes are rendered in OpenGL and elsewhere which only roughly approximates a true curved lense. Part of it is that objects that should be a constant distance (as would be the nature of a rotation, nothing is closer or further away afterwards) from the camera look as if they are changing from near to far and back as they rotate off screen.

It's possible to mitigate the effect at additional rendering cost by splitting up the screen into chunks that are have their own appropriate orientation- rather than straight into the screen, they are oriented however many degrees off-center they happen to lie. Panquake did this quite a ways back with the source to Quake 1, and I've replicated the effect for myself.


An array of cubes, floating in space. Spectacular.
A very narrow fov/zoomed in shot of some cubes.
A very wide fov shot, notice how distorted the cubes have become, while straight lines remain straight.
This is with a few dozen 'slices' to eliminate the per-cube distortion, but now we have distortion over the span of the whole array. Lines that point into the screen are still basically straight, but perpendicular ones are extremely curved.
The two points on the right and left are really 180 degrees apart from each other.
This is the result of rotating roll-wise with respect to the plane of cubes.
Behold the power of etc.

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//gluPerspective(fovSlice,(GLfloat)width/(cuts*(GLfloat)height),1.0f,1000.0f);	
			
	GLdouble xmin, xmax, ymin, ymax;
	
	float zNear = 1.0f;
	float zFar = 1000.0f;
	
	fovSlice = fov/cuts;
	float aspect = (float)width/(float)(cuts*height);
	xmax = zNear*tan(DEG_TO_RAD(fovSlice/2));
	xmin = -xmax;
	
	ymin = xmin/aspect;
	ymax = xmax/aspect;
	
	glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
	

	//////////////////////
		
	glMatrixMode(GL_MODELVIEW);
	
	theCamera->move(0, DEG_TO_RAD(fov*(-0.5 + (0.5 -  1.0)/cuts)), 0.0, 0.0, 0.0, 0.0);
	for (int i = 0; i< cuts; i++) {
		glPushMatrix();
		theCamera->move(0.0, DEG_TO_RAD(fov/cuts), 0.0,  0.0, 0.0, 0.0);
		glViewport(i*width/cuts-1,0,width/cuts+1,height);
		drawAll();	
		glPopMatrix();
	}
	theCamera->move(0.0, DEG_TO_RAD(-fov/2 + fov/(2*cuts)), 0.0, 0.0, 0.0, 0.0);
	
	////////////////////////////////////////////////

	glPopMatrix();

	glFlush();

	SDL_GL_SwapBuffers();
	
	glPopMatrix();